
using System.Collections.Generic;
using WooEngine.Common;

namespace WooEngine.Persistence
{
    public interface IDBProvider
    {
        string Tag { get; }
        bool IsHasDB { get; }
        void DeleteDB();

        void Save<T>(string key, T data);
        T Load<T>(string key);
        bool IsHasKey(string key);
        void Delete(string key);
        void Release();
        void sync();
    }

    public class DBManager : SingletonBehaviour<DBManager>
    {
#if ODIN_INSPECTOR
        [ShowInInspector, ShowIf("showOdinInfo"), DictionaryDrawerSettings(IsReadOnly = true, DisplayMode = DictionaryDisplayOptions.OneLine)]
#endif
        private readonly Dictionary<string, IDBProvider> m_dbProviders = new Dictionary<string, IDBProvider>();

        public T CreateProvider<T>(string tag, string passworld, bool isAutoSync = true) where T : IDBProvider
        {
            if(!m_dbProviders.TryGetValue(tag, out IDBProvider provider))
            {
                provider = (IDBProvider)System.Activator.CreateInstance(typeof(T), tag, passworld, isAutoSync);
                m_dbProviders.Add(tag, provider);
            }
            return (T)provider;
        }

        public void RemoveProvider(string tag)
        {
            if(m_dbProviders.TryGetValue(tag, out IDBProvider provider))
            {
                provider.Release();
                m_dbProviders.Remove(tag);
            }
        }

        public bool TryGetProvider<T>(string tag, out T provider) where T : IDBProvider
        {
            if(m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                provider = (T)result;
                return true;
            }
            provider = default;
            return false;
        }

        public bool IsHasDB(string tag) {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                return result.IsHasDB;
            }
            return false;
        }

        public void DeleteDB(string tag)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                result.DeleteDB();
            }
        }

        public void Save<T>(string tag, string key, T data)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                result.Save<T>(key, data);
            }
        }

        public T Load<T>(string tag, string key)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                return result.Load<T>(key);
            }
            return default;
        }

        public bool IsHasKey(string tag, string key)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                return result.IsHasKey(key);
            }
            return false;
        }

        public void Delete(string tag, string key)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                result.Delete(key);
            }
        }

        public void Release(string tag)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                result.Release();
            }
        }

        public void Sync(string tag)
        {
            if (m_dbProviders.TryGetValue(tag, out IDBProvider result))
            {
                result.sync();
            }
        }

        public void SyncAll()
        {
            foreach(IDBProvider result in m_dbProviders.Values)
            {
                result.sync();
            }
        }

        public void RemoveProviderAll()
        {
            foreach (IDBProvider result in m_dbProviders.Values)
            {
                result.Release();
            }
            m_dbProviders.Clear();
        }


    }
}